#pragma once 
#include <exception>

std::string as_string( const std::wstring& iString, int iCodePage=CP_ACP )
{
	if( iString.empty() )
		return std::string();

	std::string	Result;
	int		Size;

	Size = WideCharToMultiByte( iCodePage, 0, iString.data(), (int)iString.size(), NULL, 0, NULL, NULL );
	if( Size == 0 )
		return "";
	Result.resize( Size );
	Size = WideCharToMultiByte( iCodePage, 0, iString.data(), (int)iString.size(), (LPSTR)Result.data(), (int)Result.size(), NULL, NULL );
	if( Size == 0 )
		return "";
	return Result;
};

class CException : public std::exception
{
public:
	CException(const std::string& pStr) : m_message(pStr) 
	{}

	const char* what() const throw()
	{
		return m_message.c_str();
	}

protected:
	std::string m_message;
};

class CSystemException : public CException
{
public:
	CSystemException(const std::string& pStr) : CException(pStr)
	{
		m_message += "\n";
		m_message += WinError();
	}
	CSystemException(DWORD _errCode, const std::string& pStr) : CException(pStr)
	{
		m_message += "\n";
		m_message += WinError(_errCode);		
	}
private:
	std::string WinError()
	{
		DWORD err = ::GetLastError();
		return WinError(err);
	}
	std::string WinError(DWORD _errCode)
	{
		std::string _feadback("");
		LPSTR _message = NULL;

		LPVOID lpMsgBuf;

		DWORD num = FormatMessage(	FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			_errCode,
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			//_message,
			(LPTSTR) &lpMsgBuf,
			0, 
			NULL );

		if (num)
		{
			_feadback += "Error number : ";
			std::stringstream _buf;
			_buf << std::hex << _errCode;
			_feadback += _buf.str();	
			_feadback += "\n";
			_feadback += "Error description: ";
			std::wstring _temp( (wchar_t*)lpMsgBuf );
			_feadback += as_string(_temp );
			_feadback += "\n";
		}
		return _feadback;
	}
};